package com.smart.manager.member.repository;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.smart.common.entities.constant.SocKetTips;
import com.smart.common.entities.core.Page;
import com.smart.manager.member.entities.assembler.FriendDto;
import com.smart.manager.member.entities.bodys.RMemberFriend;
import com.smart.manager.member.entities.enums.FriendRelationState;
import com.smart.manager.member.entities.models.MemberMaterialPig;
import com.smart.manager.member.entities.models.MemberRelationFriend;
import com.smart.manager.member.entities.models.query.QMemberMaterialPig;
import com.smart.manager.member.entities.models.query.QMemberProfileMain;
import com.smart.manager.member.entities.models.query.QMemberRelationFriend;
import com.smart.manager.member.entities.views.MemberView;
import com.smart.manager.product.entities.enums.CameraDirection;
import com.smart.manager.product.entities.enums.PigStatus;
import com.smart.manager.product.entities.models.BasicCameraDetail;
import com.smart.manager.product.entities.models.query.QBasicCameraDetail;
import com.smart.manager.product.repository.BasicCameraDetailRepository;
import com.smart.service.socket.WebSocket;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 商店组织库
 *
 * @author Administrator
 * @date 2023/04/02
 */
@Service
@Log4j2
@RequiredArgsConstructor
public class MemberFriendRepository {

    private final WebSocket webSocket;
    private final BasicCameraDetailRepository basicCameraDetailRepository;

    public Page<MemberRelationFriend> pageList(RMemberFriend.SearchBody search) {
        QMemberRelationFriend query = new QMemberRelationFriend();
        query.order().id.desc();
        query.setFirstRow(search.firstRow()).setMaxRows(search.maxRows());
        return new Page<MemberRelationFriend>().load(query.findPagedList());
    }


    /**
     * 查询我的好友列表
     *
     * @param memberId 会员编号
     * @return {@code List<MemberRelationFriend>}
     */
    public List<FriendDto> getMyFriendList(Long memberId) {
        ArrayList<FriendDto> result = new ArrayList<>();
        new QMemberRelationFriend().state.eq(FriendRelationState.YSX).or().initiator.id.eq(memberId)
                .receiver.id.eq(memberId).endOr().order().id.desc().findEach(item -> {
                    if (!item.getInitiator().getId().equals(memberId)) {
                        MemberView initiator = item.getInitiator();

                        FriendDto mx1 = new FriendDto()
                                .setPhoneNumber(DesensitizedUtil.mobilePhone(initiator.getPhoneNumber()))
                                .setId(initiator.getId()).setAvatar(initiator.getAvatar()).setNickName(initiator.getNickName())
                                .setToken(item.getToken()).setPartner(item.getPartner());
                        result.add(mx1);
                    }


                    if (!item.getReceiver().getId().equals(memberId)) {
                        MemberView receiver = item.getReceiver();
                        FriendDto mx1 = new FriendDto()
                                .setPhoneNumber(DesensitizedUtil.mobilePhone(receiver.getPhoneNumber()))
                                .setId(receiver.getId()).setAvatar(receiver.getAvatar()).setNickName(receiver.getNickName()).setToken(item.getToken()).setPartner(item.getPartner());
                        result.add(mx1);
                    }
                });

        return result;

    }

    /**
     * @param memberId 查询申请中的好友
     * @return {@code List<MemberRelationFriend>}
     */
    public List<FriendDto> getApplyList(Long memberId) {
        return new QMemberRelationFriend().state.eq(FriendRelationState.DSX).receiver.id.eq(memberId).order().id.desc().findStream().map(item -> {
            MemberView initiator = item.getInitiator();

            return new FriendDto().setId(initiator.getId())
                    .setPhoneNumber(DesensitizedUtil.mobilePhone(initiator.getPhoneNumber()))
                    .setAvatar(initiator.getAvatar()).setNickName(initiator.getNickName())
                    .setToken(item.getToken()).setPartner(item.getPartner());

        }).collect(Collectors.toList());


    }

    /**
     * 建立好友关系
     *
     * @param memberId
     * @param body
     */
    public void applyFriend(Long memberId, RMemberFriend.ApplyBody body) {

        Assert.notEquals(memberId, body.getReceiverId(), "不能加自己为好友");
        Long friendId = new QMemberProfileMain().id.eq(body.getReceiverId()).select(QMemberProfileMain.Alias.id).findSingleAttribute();
        Assert.notNull(friendId, "添加失败:用户信息不存在");
        String friendToken = getFriendToken(memberId, body.getReceiverId());

        MemberRelationFriend relationFriend = new QMemberRelationFriend().token.eq(friendToken).setMaxRows(1).findOne();
        //不存在的好友关系 建立好友关系 已存在过的好友关系 不进行处理
        if (ObjUtil.isNull(relationFriend)) {
            MemberView memberView = new MemberView().setId(body.getReceiverId());
            MemberView initiator = new MemberView().setId(memberId);
            //socket消息
            webSocket.sendOneMessage(body.getReceiverId(), SocKetTips.noticeFriendApp);
            new MemberRelationFriend().setInitiator(initiator).setPartner(false).setReceiver(memberView).setToken(friendToken).setState(FriendRelationState.DSX).setApplyTime(LocalDateTime.now()).save();
        }

    }


    /**
     * 获取好友关系TOKEN
     *
     * @param id1 会员编号1
     * @param id2 会员编号2
     * @return {@code String}
     */
    public String getFriendToken(Long id1, Long id2) {
        String s1 = id1.toString();
        String s2 = id2.toString();
        String source = id1 > id2 ? s1.concat(s2) : s2.concat(s1);
        return DigestUtil.md5Hex16(source);
    }

    /**
     * 审核好友关系
     *
     * @param memberId 会员编号
     * @param body
     */
    public void auditFriend(Long memberId, RMemberFriend.AuditBody body) {
        MemberRelationFriend relationFriend = new QMemberRelationFriend().token.eq(body.getToken()).setMaxRows(1).findOne();
        Assert.notNull(relationFriend, "审核失败:好友关系不存在");
        Assert.equals(memberId, relationFriend.getReceiver().getId(), "审核失败:好友关系不存在");
        if (body.getApproval()) {
            //socket消息
            webSocket.sendOneMessage(relationFriend.getReceiver().getId(), SocKetTips.agreeFriendApp);
            relationFriend.setState(FriendRelationState.YSX).setPartner(false).setFinishTime(LocalDateTime.now()).update();
        } else {
            //删除好友申请
            relationFriend.delete();
        }


    }


    /**
     * 删除好友
     *
     * @param memberId member数据主键
     * @param token    好有关系令牌
     */
    public void removeFriend(Long memberId, String token) {
        MemberRelationFriend record = new QMemberRelationFriend().token.eq(token).setMaxRows(1).findOne();
        Assert.notNull(record, "删除失败:好友关系不存在");
        boolean contains = List.of(record.getReceiver().getId(), record.getInitiator()).contains(memberId);
        Assert.isTrue(contains, "删除失败:非法操作");
        Assert.isFalse(record.getPartner(), "删除失败:存在合养关系, 不能直接删除");
        record.deletePermanent();

    }


    /**
     * 判断是否是好友
     *
     * @param id1 会员id1
     * @param id2 会员id2
     * @return {@link MemberRelationFriend}
     */
    public Optional<MemberRelationFriend> isFriends(Long id1, Long id2) {
        String friendToken = getFriendToken(id1, id2);
        return new QMemberRelationFriend().token.eq(friendToken).setMaxRows(1).findOneOrEmpty();
    }


    /**
     * 查看所有猪仔
     *
     * @param id       请求ID
     * @param friendId 会员id2
     * @return {@link List}<{@link MemberMaterialPig}>
     */
    public List<MemberMaterialPig> getFriendAll(Long id, Long friendId) {
        Optional<MemberRelationFriend> friends = isFriends(id, friendId);
//        Assert.isFalse(friends.isEmpty(), "你们还是不好友请添加好友后操作");
        List<MemberMaterialPig> materialPigs = new QMemberMaterialPig().or().member.id.eq(friendId).closeMember.id.eq(friendId).endOr().status.in(PigStatus.WAIT, PigStatus.NORMAL).findList();
        for (MemberMaterialPig pig : materialPigs) {
            if (ObjUtil.isNotEmpty(pig.getPigsty())) {
                List<String> cameraCode = pig.getPigsty().getCameraCode();
                List<BasicCameraDetail> details = new QBasicCameraDetail().passageId.in(cameraCode).findList();
                CollUtil.sort(details, Comparator.comparing(BasicCameraDetail::getCameraDirection, (direction1, direction2) -> {
                    if (direction1.equals(CameraDirection.FORMER)) {
                        return -1; // 如果direction1等于"前摄像头"，则排在前面
                    } else if (direction2.equals(CameraDirection.FORMER)) {
                        return 1; // 如果direction2等于"前摄像头"，则排在前面
                    } else {
                        return 0; // 其他情况不变
                    }
                }));
                ArrayList<String> strings = new ArrayList<>();
                details.forEach(x -> {
                    strings.add(basicCameraDetailRepository.getCameraUrl(x, false));
                });
                pig.setPigsty(pig.getPigsty().setCameraUrl(strings));
            }
        }
        return materialPigs;
    }


    /**
     * 随机获取N个陌生人信息
     */
    public List<FriendDto> getStrangerListByRandom(Long loginId, Integer limit) {

        HashSet<Long> idList = new HashSet<>();
        idList.add(loginId);

        new QMemberRelationFriend().state.eq(FriendRelationState.YSX).or().initiator.id.eq(loginId)
                .receiver.id.eq(loginId).endOr().order().id.desc().findEach(item -> {
                    idList.add(item.getInitiator().getId());
                    idList.add(item.getReceiver().getId());
                });


        return new QMemberProfileMain().id.notIn(idList).setMaxRows(limit)
                .orderBy(" random() ")
                .findStream().map(x -> new FriendDto()
                        .setId(x.getId())
                        .setNickName(x.getNickName())
                        .setAvatar(x.getAvatar())
                        .setPartner(false)
                        .setToken( getFriendToken(x.getId(), loginId))
                        .setPhoneNumber(x.getPhoneNumber()))
                .collect(Collectors.toList());
    }
}
